<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Events and signals in Qt4</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Qt4, tutorial, events, signals, C++, programming, GUI, multiplatform">
<meta name="description" content="In this chapter of the Qt4 tutorial, we cover events and signals.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-5536206-1']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<div class="content2">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Events and signals in Qt4</h1>

<p>
In this part of the Qt4 C++ programming tutorial we talk about events and signals. 
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
Events are an important part in any GUI program.
All GUI applications are event-driven. An application reacts to different event 
types which are generated during it's life. Events are generated mainly by the 
user of an application. But they can be generated by other means as well. e.g. 
internet connection, window manager, timer.
In the event model, there are three participants:
</p>


<ul>
    <li>event source</li>
    <li>event object</li>
    <li>event target</li>
</ul>

<p>
The <b>event source</b> is the object whose state changes. It generates Events. 
The <b>event object</b> (Event) encapsulates the state changes in the event source.
The <b>event target</b> is the object that wants to be notified. Event source object 
delegates the task of handling an event to the event target. 
</p>

<p>
When we call the application's <code>exec()</code> method, the application
enters the main loop. The main loop fetches events and sends them to the objects. 
Trolltech has introduced a unique signal and slot mechanism.
This signal and slot mechanism is an extension to the C++ programming language. 
</p>

<p>
Signals and slots are used for communication between objects. A <b>signal</b> 
is emitted when a particular event occurs. A <b>slot</b> is a normal C++ method. 
A slot is called when a signal connected to it is emitted.
</p>


<h2>Click</h2>

<p>
The first example shows a very simple event handling example. We have one push 
button. By clicking on the push button, we terminate the application. 
</p>

<div class="codehead">lines.h</div>
<pre class="code">
#pragma once

#include &lt;QWidget&gt;

class Click : public QWidget
{
  public:
    Click(QWidget *parent = 0);

};
</pre>

<p>
Header file. 
</p>

<div class="codehead">lines.cpp</div>
<pre class="code">
#include &lt;QPushButton&gt;
#include &lt;QApplication&gt;
#include "click.h"

Click::Click(QWidget *parent)
    : QWidget(parent)
{
  QPushButton *quit = new QPushButton("Quit", this);
  quit->setGeometry(50, 40, 75, 30);

  connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}
</pre>

<p>
We display a <code>QPushButton</code> on the window. 
</p>

<pre class="explanation">
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
</pre>

<p>
The <code>connect()</code> method connects a signal to the slot. When we click on the quit button, 
the <code>clicked()</code> signal is generated. The <code>qApp</code> is a global pointer to the
application object. It is defined in the &lt;QApplication&gt; header file. The <code>quit()</code> method
is called, when the clicked signal is emitted. 
</p>

<div class="codehead">main.cpp</div>
<pre class="code">
#include &lt;Application&gt;
#include "click.h"

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);  
    
  Click window;
  
  window.move(300, 300);
  window.resize(250, 150);
  window.setWindowTitle("Click");
  window.show();

  return app.exec();
}
</pre>

<p>
Main file. 
</p>


<img src="/img/gui/qt4/click.png" alt="Click">
<div class="figure">
Figure: Click
</div>


<h2>KeyPress</h2>

<p>
In the following example, we will react to a key press.
</p>

<div class="codehead">keypress.h</div>
<pre class="code">
#pragma once

#include &lt;QWidget&gt;

class KeyPress : public QWidget
{
  public:
    KeyPress(QWidget *parent = 0);

  protected:
    void keyPressEvent(QKeyEvent * e);
};
</pre>

<p>
Header file. 
</p>

<div class="codehead">keypress.cpp</div>
<pre class="code">
#include &lt;QApplication&gt;
#include &lt;QKeyEvent&gt;

#include "keypress.h"

KeyPress::KeyPress(QWidget *parent)
    : QWidget(parent)
{

}

void KeyPress::keyPressEvent(QKeyEvent *event)
{
   if (event->key() == Qt::Key_Escape) {  
       qApp->quit();
   } 
}
</pre>

<p>
The application terminates, if we press the Escape key. 
</p>

<pre class="explanation">
void KeyPress::keyPressEvent(QKeyEvent *e)
{
   if (e->key() == Qt::Key_Escape) {  
       qApp->quit();
   } 
}
</pre>

<p>
One of the ways of working with events in Qt4 programming library is 
to reimplement an event handler. The <code>QKeyEvent</code> is an event 
object, which holds information about what has happened. 
In our case, we use the event object to determine, which key was 
actually pressed. 
</p>

<div class="codehead">main.cpp</div>
<pre class="code">
#include &lt;QApplication&gt;
#include "keypress.h"

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);  
    
  KeyPress window;
  
  window.resize(250, 150);
  window.move(300, 300);
  window.setWindowTitle("Key press");
  window.show();

  return app.exec();
}
</pre>

<p>
Main file. 
</p>


<h2>QMoveEvent</h2>

<p>
The <code>QMoveEvent</code> class contains event parameters for move events.
Move events are sent to widgets that have been moved.
</p>

<div class="codehead">move.h</div>
<pre class="code">
#pragma once

#include &lt;QMainWindow&gt;

class Move : public QWidget
{
  Q_OBJECT

  public:
    Move(QWidget *parent = 0);
 
  protected:
    void moveEvent(QMoveEvent *e);

};
</pre>

<p>
Header file. 
</p>

<div class="codehead">move.cpp</div>
<pre class="code">
#include &lt;QMoveEvent&gt;
#include "move.h"

Move::Move(QWidget *parent)
    : QWidget(parent)
{
  
}

void Move::moveEvent(QMoveEvent *e)
{
  int x = e->pos().x();
  int y = e->pos().y();
  
  QString text = QString::number(x) + "," + QString::number(y);

  setWindowTitle(text);
}
</pre>

<p>
In our code programming example, we react to a move event. We determine 
the current x, y coordinates of the upper left corner of the client area 
of the window and set those values to the title of the window. 
</p>

<pre class="explanation">
int x = e->pos().x();
int y = e->pos().y();
</pre>

<p>
We use the <code>QMoveEvent</code> object to determine the x, y values. 
</p>

<pre class="explanation">
QString text = QString::number(x) + "," + QString::number(y);
</pre>

<p>
We convert the integer values to strings.
</p>

<pre class="explanation">
setWindowTitle(text);
</pre>

<p>
Set the text to the title of the window. 
</p>

<div class="codehead">main.cpp</div>
<pre class="code">
#include &lt;QApplication&gt;
#include "move.h"

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);  
    
  Move window;
  
  window.resize(250, 150);
  window.move(300, 300);
  window.setWindowTitle("Move");
  window.show();
  
  return app.exec();
}
</pre>

<p>
Main file. 
</p>


<img src="/img/gui/qt4/move.png" alt="QMoveEvent">
<div class="figure">
Figure: QMoveEvent
</div>


<h2>Disconnecting an signal</h2>

<p>
A signal can be disconnected from the slot. The next example will 
show, how we can accomplish this. 
</p>

<div class="codehead">disconnect.h</div>
<pre class="code">
#pragma once

#include &lt;QWidget&gt;
#include &lt;QPushButton&gt;

class Disconnect : public QWidget
{
  Q_OBJECT  

  public:
    Disconnect(QWidget *parent = 0);

  private slots:
    void onClick();
    void onCheck(int);

  private:
    QPushButton *click;
};
</pre>

<p>
In the header file, we have declared two slots. The 
<code>slots</code> is not a C++ keyword. It is 
a Qt4 programming library extension. These extensions are 
handled by the preprocessor, before the code is compiled. 
When we use signals and slots in our classes, we must provide 
a <code>Q_OBJECT</code> macro at the beginnig of the 
class definition. Otherwise, the preprocessor would complain. 
</p>

<div class="codehead">disconnect.cpp</div>
<pre class="code">
#include &lt;QTextStream&gt;
#include &lt;QCheckBox&gt;
#include "disconnect.h"

Disconnect::Disconnect(QWidget *parent)
    : QWidget(parent)
{
  click = new QPushButton("Click", this);
  click->setGeometry(50, 40, 75, 30);

  QCheckBox *cb = new QCheckBox("Connect", this);
  cb->setCheckState(Qt::Checked);
  cb->move(150, 40);

  connect(click, SIGNAL(clicked()), this, SLOT(onClick()));
  connect(cb, SIGNAL(stateChanged(int)), this, SLOT(onCheck(int)));  
}

void Disconnect::onClick() 
{
  QTextStream out(stdout);
  out &lt;&lt; "Button clicked" &lt;&lt;  endl;
}

void Disconnect::onCheck(int state)
{
  if (state == Qt::Checked) {
    connect(click, SIGNAL(clicked()), this, SLOT(onClick()));
  } else {
    click->disconnect(SIGNAL(clicked()));
  }
}
</pre>

<p>
In our example, we have a button and a check box. The check box connects and disconnects a 
slot from the buttons clicked signal. This example must be executed from the command line. 
</p>

<pre class="explanation">
connect(click, SIGNAL(clicked()), 
    this, SLOT(onClick()));
connect(cb, SIGNAL(stateChanged(int)), 
    this, SLOT(onCheck(int)));
</pre>

<p>
Here we connect signals to our user defined slots. 
</p>

<pre class="explanation">
void Disconnect::onClick() 
{
  QTextStream out(stdout);
  out &lt;&lt; "Button clicked" &lt;&lt; endl;
}
</pre>

<p>
If we click on the click button, we send "Button clicked" text to the terminal window. 
</p>

<pre class="explanation">
void Disconnect::onCheck(int state)
{
  if (state == Qt::Checked) {
    connect(click, SIGNAL(clicked()), 
        this, SLOT(onClick()));
  } else {
    click->disconnect(SIGNAL(clicked()));
  }
}
</pre>

<p>
Inside the <code>onCheck()</code> slot, we connect/disconnect an 
<code>onClick()</code> slot
from the click button. 
</p>

<div class="codehead">main.cpp</div>
<pre class="code">
#include &lt;QApplication&gt;
#include "disconnect.h"

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);  
    
  Disconnect window;
  
  window.resize(250, 150);
  window.move(300, 300);
  window.setWindowTitle("Disconnect");
  window.show();
  
  return app.exec();
}
</pre>

<p>
Main file. 
</p>


<h2>Timer</h2>

<p>
A timer is used to implement single shot or repetitive tasks. A good example 
where we use a timer is a clock. Each second we must update our label displaying 
the current time.
</p>


<div class="codehead">timer.h</div>
<pre class="code">
#pragma once

#include &lt;QWidget&gt;
#include &lt;QLabel&gt;

class Timer : public QWidget
{
  public:
    Timer(QWidget *parent = 0);

  protected:
    void timerEvent(QTimerEvent *e);

  private:
    QLabel *label;
};
</pre>

<p>
Header file. 
</p>

<div class="codehead">timer.cpp</div>
<pre class="code">
#include &lt;QTime&gt;
#include "timer.h"

Timer::Timer(QWidget *parent)
    : QWidget(parent)
{   
  label = new QLabel("", this);
  label->move(50, 50);

  QTime qtime = QTime::currentTime();
  QString stime = qtime.toString();
  label->setText(stime);
   
  startTimer(1000);
}

void Timer::timerEvent(QTimerEvent *e)
{
  Q_UNUSED(e);
  
  QTime qtime = QTime::currentTime();
  QString stime = qtime.toString();
  label->setText(stime);
}
</pre>

<p>
In our example, we display a current local time on the window. 
</p>


<pre class="explanation">
label = new QLabel("", this);
label->move(50, 50);
</pre>

<p>
To display a time, we use a label widget. 
</p>

<pre class="explanation">
QTime qtime = QTime::currentTime();
QString stime = qtime.toString();
label->setText(stime);
</pre>

<p>
Here we determine the current local time. We set it to the label widget. 
</p>

<pre class="explanation">
startTimer(1000);
</pre>

<p>
We start the timer. Every 1000ms a timer event is generated. 
</p>

<pre class="explanation">
void Timer::timerEvent(QTimerEvent *e)
{
  Q_UNUSED(e);
  
  QTime qtime = QTime::currentTime();
  QString stime = qtime.toString();
  label->setText(stime);
}
</pre>

<p>
To work with timer events, we must reimplement the <code>timerEvent()</code> method. 
</p>

<div class="codehead">main.cpp</div>
<pre class="code">
#include &lt;QApplication&gt;
#include "timer.h"

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);  
    
  Timer window;
  
  window.move(300, 300);
  window.resize(150, 100);
  window.setWindowTitle("Timer");
  window.show();

  return app.exec();
}
</pre>

<p>
Main file. 
</p>


<img src="/img/gui/qt4/timer.png" alt="Timer">
<div class="figure">
Figure: Timer
</div>

<p>
This chapter was dedicated to events and signals in Qt4.
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified October 24, 2012  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

